
package perftest;

import com.google.protobuf.InvalidProtocolBufferException;
import java.util.*;
import biobuf.util.*;

import biobuf.util.TimeMemCheck;
import biobuf.util.MemCheck;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.collections.primitives.IntList;
import org.apache.commons.collections.primitives.ArrayIntList;

/**
 */
public class Benchmarks {
    static int ARRAY_SIZE = 1000000; 
    static int INITIAL_OFFSET = 50000000;
    static int WARMUP_RUNS = 20;

    public static void main(String[] args)  {
	System.out.println("Running perftest.Benchmarks");
	System.out.println("Doing benchmark warmups to kick in JIT");
	    
        for (int i=0; i<WARMUP_RUNS; i++)  {
	    System.out.print("   warmup run: " + i);
	    doBenchmarks(false);
	}
	// gcAndReport(null);
	System.out.println();
	doBenchmarks(true);
    }

    public static void doBenchmarks(boolean report)  {
	List results = new ArrayList();
        try {
	    if (report)  { gcAndReport(null); }
            results.add( doSimpleArraysTest(report) );
	    if (report)  { gcAndReport(null); }
            results.add( doModSimpleArraysTest(report) );
	    if (report)  { gcAndReport(null); }
        } catch (Exception ex) {
            Logger.getLogger(Benchmarks.class.getName()).log(Level.SEVERE, null, ex);
        }
	// trying to make sure none of primary data gets gc'd when reporting on tests
	//        if (report)  { System.out.println(results.size()); }
	// System.gc();
    }


    public static void gcAndReport(TimeMemCheck tmc)  { gcAndReport(tmc, null); }
    public static void gcAndReport(TimeMemCheck tmc, String label)  {
	System.gc(); 
	if (tmc != null)  { tmc.timeStop(); }
	try  {
	    Thread.currentThread().sleep(2000); 
	}
	catch (Exception ex)  { ex.printStackTrace(); }
	if (tmc != null)  {
	    tmc.report(label);
	    tmc.reset(); 
	    tmc.start();
	}
    }

    public static SimpleArrays.SimpleIntArray doSimpleArraysTest(boolean report)
    	throws InvalidProtocolBufferException   {

	if (report)  { System.out.println("SimpleIntArray Benchmarking"); }
	TimeMemCheck tmem = new TimeMemCheck("   SimpleIntArray", MemCheck.mB);
	tmem.start();
	SimpleArrays.SimpleIntArray.Builder arrayB = SimpleArrays.SimpleIntArray.newBuilder();
	for (int i=0; i<ARRAY_SIZE; i++)  {
	    int val = i + INITIAL_OFFSET;
	    arrayB.addFoo(val);
	}
	SimpleArrays.SimpleIntArray array = arrayB.build();
	if (report)  {  gcAndReport(tmem, "   Build Protobuf:  "); }
	byte[] wire_format = array.toByteArray();
	if (report)  {  gcAndReport(tmem, "   Write Protobuf:  "); }
	SimpleArrays.SimpleIntArray new_array = SimpleArrays.SimpleIntArray.parseFrom(wire_format);
	if (report)  {  gcAndReport(tmem, "   Read Protobuf:   "); }
	if (report)  { System.out.println(); }

	return new_array;
    }


    public static ModSimpleArrays.SimpleIntArray doModSimpleArraysTest(boolean report) 
	throws InvalidProtocolBufferException   {
	if (report)  { System.out.println("ModSimpleIntArray Benchmarking"); }
	TimeMemCheck tmem = new TimeMemCheck("   ModSimpleIntArray", MemCheck.mB);
	tmem.start();
	ModSimpleArrays.SimpleIntArray.Builder arrayB = ModSimpleArrays.SimpleIntArray.newBuilder();
	for (int i=0; i<ARRAY_SIZE; i++)  {
	    int val = i + INITIAL_OFFSET;
	    arrayB.addFoo(val);
	}
	ModSimpleArrays.SimpleIntArray array = arrayB.build();
	if (report)  {  gcAndReport(tmem, "   Build Protobuf:  "); }
	byte[] wire_format = array.toByteArray();
	if (report)  {  gcAndReport(tmem, "   Write Protobuf:  "); }
	ModSimpleArrays.SimpleIntArray new_array = ModSimpleArrays.SimpleIntArray.parseFrom(wire_format);
	if (report)  {  gcAndReport(tmem, "   Read Protobuf:   "); }
	if (report)  { System.out.println(); }
	return new_array;
    }


}